package org.example.rzfx.service;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
 import org.example.rzfx.config.GlobalConfig;
import org.example.rzfx.entity.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 日志缓存服务 - Redis缓存层
 * 
 * 功能：
 * 1. 日志先写入Redis，提高写入性能
 * 2. 提供批量读取接口供定时任务回写MySQL
 * 3. 自动过期机制，避免Redis占用过多内存（过期时间从全局配置读取）
 */
@Service
public class LogCacheService {
    
    private static final Logger logger = LoggerFactory.getLogger(LogCacheService.class);
    
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    
    @Resource
    private GlobalConfig globalConfig;
    
    /**
     * Redis Key前缀：log:cache:日期
     * 例如: log:cache:2024-01-15
     */
    private static final String LOG_CACHE_PREFIX = "log:cache:";
    
    /**
     * 保存日志到Redis缓存
     * 
     * @param log 日志对象
     * @return 是否保存成功
     */
    public boolean saveToCache(Log log) {
        try {
            // 生成缓存Key（按日期分组，便于批量处理）
            String date = log.getTimestamp().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String cacheKey = LOG_CACHE_PREFIX + date;
            
            // 使用日志的唯一hash作为field，避免重复
            String field = log.getUniqueHash();
            
            // 序列化为JSON存储
            String jsonValue = JSON.toJSONString(log);
            
            // 存入Redis Hash结构
            redisTemplate.opsForHash().put(cacheKey, field, jsonValue);
            
            // 设置过期时间（从全局配置动态读取，每次写入都重置，确保当天的日志不会提前过期）
            long expireHours = globalConfig.getCacheExpireHours();
            redisTemplate.expire(cacheKey, expireHours, TimeUnit.HOURS);
            
            logger.debug("日志已缓存到Redis: key={}, hash={}, 过期时间={}小时", cacheKey, field, expireHours);
            return true;
            
        } catch (Exception e) {
            logger.error("保存日志到Redis缓存失败", e);
            return false;
        }
    }
    
    /**
     * 批量保存日志到Redis
     * 
     * @param logs 日志列表
     * @return 成功保存的数量
     */
    public int batchSaveToCache(List<Log> logs) {
        if (logs == null || logs.isEmpty()) {
            return 0;
        }
        
        int successCount = 0;
        for (Log log : logs) {
            if (saveToCache(log)) {
                successCount++;
            }
        }
        
        logger.info("批量缓存日志完成: 总数={}, 成功={}", logs.size(), successCount);
        return successCount;
    }
    
    /**
     * 获取指定日期的所有缓存日志
     * 
     * @param date 日期字符串，格式：yyyy-MM-dd
     * @return 日志列表
     */
    public List<Log> getCachedLogs(String date) {
        try {
            String cacheKey = LOG_CACHE_PREFIX + date;
            
            // 从Redis Hash中获取所有日志
            List<Object> values = redisTemplate.opsForHash().values(cacheKey);
            
            if (values == null || values.isEmpty()) {
                logger.info("Redis中没有找到日期 {} 的缓存日志", date);
                return new ArrayList<>();
            }
            
            // 反序列化
            List<Log> logs = new ArrayList<>();
            for (Object value : values) {
                try {
                    Log logEntity = JSON.parseObject(value.toString(), Log.class);
                    
                    // 清理fields字段，确保是有效JSON或null
                    if (logEntity.getFields() != null && !logEntity.getFields().isEmpty()) {
                        try {
                            // 验证是否为有效JSON
                            JSONObject.parseObject(logEntity.getFields());
                        } catch (Exception e) {
                            logger.warn("日志fields字段不是有效JSON，已清空: hash={}", logEntity.getUniqueHash());
                            logEntity.setFields(null);
                        }
                    }
                    
                    logs.add(logEntity);
                } catch (Exception e) {
                    logger.error("解析缓存日志失败: {}", value, e);
                }
            }
            
            logger.info("从Redis获取到 {} 条日期为 {} 的日志", logs.size(), date);
            return logs;
            
        } catch (Exception e) {
            logger.error("从Redis获取缓存日志失败: date={}", date, e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 获取所有需要回写的日期列表
     * 
     * @return 日期列表
     */
    public List<String> getPendingDates() {
        try {
            // 扫描所有 log:cache:* 的key
            Set<String> keys = redisTemplate.keys(LOG_CACHE_PREFIX + "*");
            
            if (keys == null || keys.isEmpty()) {
                return new ArrayList<>();
            }
            
            // 提取日期部分
            List<String> dates = new ArrayList<>();
            for (String key : keys) {
                String date = key.replace(LOG_CACHE_PREFIX, "");
                dates.add(date);
            }
            
            logger.info("发现 {} 个待回写的日期分组", dates.size());
            return dates;
            
        } catch (Exception e) {
            logger.error("获取待回写日期列表失败", e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 删除指定日期的缓存（回写成功后调用）
     * 
     * @param date 日期字符串
     * @return 是否删除成功
     */
    public boolean deleteCachedLogs(String date) {
        try {
            String cacheKey = LOG_CACHE_PREFIX + date;
            Boolean result = redisTemplate.delete(cacheKey);
            
            if (Boolean.TRUE.equals(result)) {
                logger.info("已删除日期 {} 的缓存日志", date);
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            logger.error("删除缓存日志失败: date={}", date, e);
            return false;
        }
    }
    
    /**
     * 删除指定日志（用于去重或错误修正）
     * 
     * @param date 日期
     * @param uniqueHash 日志唯一hash
     * @return 是否删除成功
     */
    public boolean deleteCachedLog(String date, String uniqueHash) {
        try {
            String cacheKey = LOG_CACHE_PREFIX + date;
            Long result = redisTemplate.opsForHash().delete(cacheKey, uniqueHash);
            
            return result != null && result > 0;
            
        } catch (Exception e) {
            logger.error("删除单条缓存日志失败: date={}, hash={}", date, uniqueHash, e);
            return false;
        }
    }
    
    /**
     * 获取指定日期的缓存日志数量
     * 
     * @param date 日期
     * @return 日志数量
     */
    public long getCachedLogCount(String date) {
        try {
            String cacheKey = LOG_CACHE_PREFIX + date;
            Long size = redisTemplate.opsForHash().size(cacheKey);
            return size != null ? size : 0;
            
        } catch (Exception e) {
            logger.error("获取缓存日志数量失败: date={}", date, e);
            return 0;
        }
    }
    
    /**
     * 获取所有缓存日志的总数量
     * 
     * @return 总数量
     */
    public long getTotalCachedCount() {
        try {
            List<String> dates = getPendingDates();
            long total = 0;
            
            for (String date : dates) {
                total += getCachedLogCount(date);
            }
            
            return total;
            
        } catch (Exception e) {
            logger.error("获取缓存日志总数失败", e);
            return 0;
        }
    }
}

